﻿using BCCommon.FreightEnums;
using BCData.TMS.DisableArea;
using BCData.TMS.DisableArea.DisableAreaRangeCoordinate;
using BCData.TMS.DisableArea.DisableAreaVehicleTypeReference;
using BCDto.TMS.DisableArea;
using BCDto.TMS.DisableArea.DisableAreaRangeCoordinate;
using BCDto.TMS.DisableArea.DisableAreaVehicleTypeReference;
using BCDto.Sim.Admin.Admin;
using BCEntity.TMS.DisableArea;
using BCEntity.TMS.DisableArea.DisableAreaRangeCoordinate;
using BCEntity.TMS.DisableArea.DisableAreaVehicleTypeReference;
using BCService.Common.Area;
using BCService.Utils;
using BCService.TMS.VehicleTypeService;
using System;
using System.Collections.Generic;
using System.Linq;

namespace BCService.TMS.DisableArea
{
    public class DisableAreaService : IDisableAreaService
    {
        private readonly IDisableAreaData disableAreaData;
        private readonly IProvinceService provinceService;
        private readonly ICityService cityService;
        private readonly ICountyService countyService;
        private readonly IDisableAreaRangeCoordinateData disableAreaRangeCoordinateData;
        private readonly IDisableAreaVehicleTypeReferenceData disableAreaVehicleTypeReferenceData;
        private readonly IVehicleTypeService vehicleTypeService;

        public DisableAreaService(IDisableAreaData disableAreaData, 
            IProvinceService provinceService, 
            ICityService cityService, 
            ICountyService countyService, 
            IDisableAreaRangeCoordinateData disableAreaRangeCoordinateData, 
            IDisableAreaVehicleTypeReferenceData disableAreaVehicleTypeReferenceData,
            IVehicleTypeService vehicleTypeService)
        {
            this.disableAreaData = disableAreaData;
            this.provinceService = provinceService;
            this.cityService = cityService;
            this.countyService = countyService;
            this.disableAreaRangeCoordinateData = disableAreaRangeCoordinateData;
            this.disableAreaVehicleTypeReferenceData = disableAreaVehicleTypeReferenceData;
            this.vehicleTypeService = vehicleTypeService;
        }

        /// <summary>
        /// 查询禁卸货区域信息
        /// </summary>
        /// <returns></returns>
        public IEnumerable<DisableAreaDto> GetDisableAreaInfo(string provinceCode, string cityCode)
        {
            var displayArea = this.disableAreaData.GetDisableAreaInfo(provinceCode, cityCode);

            List<DisableAreaDto> result = displayArea.As<List<DisableAreaDto>>();

            foreach (var item in result)
            {
                var rangeresult = this.disableAreaRangeCoordinateData.QueryDisableAreaRangeCoordinate(item.DisableAreaId).Result;
                var typeresult = this.disableAreaVehicleTypeReferenceData.QueryDisableAreaVehicleTypeReference(item.DisableAreaId).Result;
                item.RangeCoordinateList = rangeresult.Where(p => p.DisableAreaId == item.DisableAreaId).As<List<DisableAreaRangeCoordinateDto>>();
                item.VehicleTypeReferenceList = typeresult.Where(p => p.DisableAreaId == item.DisableAreaId).As<List<DisableAreaVehicleTypeReferenceDto>>();
            }

            return result;
        }

        /// <summary>
        ///查询禁卸货区域坐标 
        /// </summary>
        /// <param name="disableAreaId"></param>
        /// <returns></returns>
        public IEnumerable<DisableAreaRangeCoordinateDto> QueryDisableAreaRangeCoordinate(long disableAreaId)
        {
            return this.disableAreaRangeCoordinateData.QueryDisableAreaRangeCoordinate(disableAreaId).Result.As<IEnumerable<DisableAreaRangeCoordinateDto>>();
        }

        /// <summary>
        /// 查询禁卸货区域车辆类型
        /// </summary>
        /// <param name="disableAreaId"></param>
        /// <returns></returns>
        public IEnumerable<DisableAreaVehicleTypeReferenceDto> QueryDisableAreaVehicleTypeReference(long disableAreaId)
        {
            return this.disableAreaVehicleTypeReferenceData.QueryDisableAreaVehicleTypeReference(disableAreaId).Result.As<IEnumerable<DisableAreaVehicleTypeReferenceDto>>();
        }

        /// <summary>
        /// 新增禁卸货区域信息
        /// </summary>
        /// <param name="adminDto"></param>
        /// <param name="dto"></param>
        /// <param name="rangeCoordinateList"></param>
        /// <param name="vehicleTypeReferenceList"></param>
        /// <returns></returns>
        public DisableAreaDto AddDisableArea(AdminDto adminDto, DisableAreaRequestDto dto, List<DisableAreaRangeCoordinateDto> rangeCoordinateList, List<DisableAreaVehicleTypeReferenceDto> vehicleTypeReferenceList)
        {
            var provinceDto = this.provinceService.GetProvinceEntity(dto.ProvinceCode);
            if (provinceDto == null)
            {
                throw new ArgumentException("省份编码错误");
            }
            var cityDto = this.cityService.Get(dto.CityCode);
            if (cityDto == null)
            {
                throw new ArgumentException("城市编码错误");
            }
            if (cityDto.ProvinceCode != dto.ProvinceCode)
            {
                throw new ArgumentException("当前省份不存在此城市");
            }
            if (!rangeCoordinateList.Any())
            {
                throw new ArgumentException("禁止区域范围坐标不允许为空");
            }

            string rangeCoordinate = string.Join(';', rangeCoordinateList.Select(p => string.Format("{0},{1}", p.Longitude, p.Latitude)));

            if (rangeCoordinate.Length > 4000)
            {
                throw new ArgumentException("坐标范围最大不能超过4000字符");
            }

            if (dto.DisableType == DisableAreaType.TimeRange)
            {
                if (!dto.OpenTime.HasValue || !dto.CloseTime.HasValue)
                {
                    throw new ArgumentException("禁止类型为时间段时，请输入开放时间及关闭时间");
                }
            }

            DisableAreaEntity disableAreaEntity = dto.As<DisableAreaEntity>();
            disableAreaEntity.EditerAdminId = adminDto.AdminId;
            disableAreaEntity.Editer = adminDto.FullName;
            disableAreaEntity.RangeCoordinate = rangeCoordinate;
            disableAreaEntity.DisableType = dto.DisableType;
            disableAreaEntity.OpenTime = dto.OpenTime;
            disableAreaEntity.CloseTime = dto.CloseTime;
            disableAreaEntity.Enabled = true;

            var res = this.disableAreaData.AddDisableArea(disableAreaEntity);
            var result = res.GetAwaiter().GetResult();
            if (result == null)
            {
                throw new ArgumentException("创建禁止装卸货区域时错误");
            }

            List<DisableAreaRangeCoordinateEntity> disableAreaRangeCoordinateEntities = rangeCoordinateList.As<List<DisableAreaRangeCoordinateEntity>>();

            int rangeResult = this.disableAreaRangeCoordinateData.Add(result.DisableAreaId, disableAreaRangeCoordinateEntities).GetAwaiter().GetResult();
            if (rangeResult <= 0)
            {
                this.disableAreaData.Delete(result.DisableAreaId);
                this.disableAreaRangeCoordinateData.Delete(result.DisableAreaId);
                throw new ArgumentException("创建禁止装卸货区域坐标记录时错误");
            }

            List<DisableAreaVehicleTypeReferenceEntity> disableAreaVehicleTypeReferenceEntities = vehicleTypeReferenceList.As<List<DisableAreaVehicleTypeReferenceEntity>>();

            int vehicleResult = this.disableAreaVehicleTypeReferenceData.Add(result.DisableAreaId, disableAreaVehicleTypeReferenceEntities).GetAwaiter().GetResult();
            if (vehicleResult <= 0)
            {
                this.disableAreaData.Delete(result.DisableAreaId);
                this.disableAreaVehicleTypeReferenceData.Delete(result.DisableAreaId);
                throw new ArgumentException("添加禁止装卸货区域被禁止车型记录时错误");
            }
            DisableAreaDto disableArea = result.As<DisableAreaDto>();
            disableArea.RangeCoordinateList = rangeCoordinateList;
            disableArea.VehicleTypeReferenceList = vehicleTypeReferenceList;
            return disableArea;
        }

        /// <summary>
        /// 修改禁卸货区域信息
        /// </summary>
        /// <param name="adminDto"></param>
        /// <param name="dto"></param>
        /// <param name="rangeCoordinateList"></param>
        /// <param name="vehicleTypeReferenceList"></param>
        /// <param name="disableAreaId"></param>
        /// <returns></returns>
        public DisableAreaDto UpdateDisableArea(AdminDto adminDto, DisableAreaRequestDto dto, List<DisableAreaRangeCoordinateDto> rangeCoordinateList, List<DisableAreaVehicleTypeReferenceDto> vehicleTypeReferenceList, long disableAreaId)
        {
            var provinceDto = this.provinceService.GetProvinceEntity(dto.ProvinceCode);
            if (provinceDto == null)
            {
                throw new ArgumentException("省份编码错误");
            }
            var cityDto = this.cityService.Get(dto.CityCode);
            if (cityDto == null)
            {
                throw new ArgumentException("城市编码错误");
            }
            if (cityDto.ProvinceCode != dto.ProvinceCode)
            {
                throw new ArgumentException("当前省份不存在此城市");
            }
            if (!rangeCoordinateList.Any())
            {
                throw new ArgumentException("禁止区域范围坐标不允许为空");
            }
            string rangeCoordinate = string.Join(';', rangeCoordinateList.Select(p => string.Format("{0},{1}", p.Longitude, p.Latitude)));
            if (rangeCoordinate.Length > 4000)
            {
                throw new ArgumentException("坐标范围最大不能超过4000字符");
            }
            if (dto.DisableType == DisableAreaType.TimeRange)
            {
                if (!dto.OpenTime.HasValue || !dto.CloseTime.HasValue)
                {
                    throw new ArgumentException("禁止类型为时间段时，请输入开放时间及关闭时间");
                }
            }

            foreach (var item in vehicleTypeReferenceList)
            {
                if (this.vehicleTypeService.GetById(item.VehicleTypeId)==null){
                    throw new ArgumentException("所选车型不存在，请正确操作");
                }
            }

            DisableAreaEntity disableAreaEntity  = dto.As<DisableAreaEntity>();
            this.disableAreaRangeCoordinateData.Delete(disableAreaId);
            this.disableAreaRangeCoordinateData.Delete(disableAreaId);
            disableAreaEntity.DisableAreaId = disableAreaId;
            disableAreaEntity.RangeCoordinate = rangeCoordinate;
            disableAreaEntity.EditerAdminId = adminDto.AdminId;
            disableAreaEntity.Editer = adminDto.FullName;

            var result = this.disableAreaData.UpdateDisableArea(disableAreaEntity).GetAwaiter().GetResult();
            if (result == null)
            {
                throw new ArgumentException("修改禁止装卸货区域时错误");
            }

            List<DisableAreaRangeCoordinateEntity> disableAreaRangeCoordinateEntities = rangeCoordinateList.As<List<DisableAreaRangeCoordinateEntity>>();
            int status = 0;
            while (status == 0) {
                status = this.disableAreaRangeCoordinateData.Add(result.DisableAreaId, disableAreaRangeCoordinateEntities).GetAwaiter().GetResult();
            }
            
            List<DisableAreaVehicleTypeReferenceEntity> disableAreaVehicleTypeReferenceEntities = vehicleTypeReferenceList.As<List<DisableAreaVehicleTypeReferenceEntity>>();
            status = 0;
            while (status == 0)
            {
                status = this.disableAreaVehicleTypeReferenceData.Add(result.DisableAreaId, disableAreaVehicleTypeReferenceEntities).GetAwaiter().GetResult();
            }

            DisableAreaDto disableArea = result.As<DisableAreaDto>();
            disableArea.RangeCoordinateList = rangeCoordinateList.As<List<DisableAreaRangeCoordinateDto>>();
            disableArea.VehicleTypeReferenceList = vehicleTypeReferenceList.As<List<DisableAreaVehicleTypeReferenceDto>>();
            return disableArea;
        }
        /// <summary>
        /// 删除禁卸货区域
        /// </summary>
        /// <param name="disableAreaId"></param>
        public bool DeleteDisableArea(long disableAreaId)
        {
            bool a = this.disableAreaData.Delete(disableAreaId);
            bool b = this.disableAreaRangeCoordinateData.Delete(disableAreaId);
            bool c = this.disableAreaVehicleTypeReferenceData.Delete(disableAreaId);
            if (a && b && c)
            {
                return true;
            }
            return false;
        }
    }
}
